#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
 
#include "data_type.h"
#include "alloc.h"
#include "memfunc.h"
#include "basefunc.h"
#include "struct_deal.h"
#include "crypto_func.h"
#include "memdb.h"
#include "message.h"
#include "ex_module.h"
#include "sys_func.h"
#include "tcm_constants.h"
#include "tcm_structures.h"
#include "tcm_libinfo.h"
#include "tcmfunc.h"

#include "tcm_cube_struct.h"
#include "tcm_key_manage.h"
#include "tcm_key_desc.h"

#include "tcm_libinit.h"
// add para lib_include
int tcm_libinit_init(void * sub_proc, void * para)
{
	int ret;
	// Init Tcm Func

    struct tcm_libinit_para * tcm_para=para;
    if((tcm_para==NULL) || (tcm_para->tcm_type==0))
    // normal tcm device
    {
	    ret=TCM_LibInit();
    }
    else if(tcm_para->tcm_type == 1)
    // virtual tcm device, need to change node_uuid to a virtual uuid
    // and call TCM_SetLibInfo to change device 
    {
        RECORD(TCM_LIBINFO,LIBINFO) * tcm_libinfo;
        tcm_libinfo =Talloc0(sizeof(*tcm_libinfo));
        if(tcm_libinfo ==NULL)
            return -ENOMEM;
        Strncpy(tcm_libinfo->dev_name,tcm_para->dev_name,DIGEST_SIZE);
        tcm_libinfo->type=tcm_para->tcm_type;
        Strncpy(tcm_libinfo->node_name,tcm_para->node_name,DIGEST_SIZE);
        calculate_context_sm3(tcm_libinfo->node_name,Strlen(tcm_libinfo->node_name),tcm_libinfo->node_uuid);
        ret=TCM_SetLibInfo(tcm_libinfo);
        if(ret<0)
            return ret;
    }
    else if(tcm_para->tcm_type == 2)
    // network tcm device, should use tcp link to connect with tcm emulator
    // and change vtcmutils_transmit function 
    {
        RECORD(TCM_LIBINFO,LIBINFO) * tcm_libinfo;
        tcm_libinfo =Talloc0(sizeof(*tcm_libinfo));
        if(tcm_libinfo ==NULL)
            return -ENOMEM;
        Strncpy(tcm_libinfo->dev_name,tcm_para->dev_name,DIGEST_SIZE);
        tcm_libinfo->type=tcm_para->tcm_type;
        Strncpy(tcm_libinfo->node_name,tcm_para->node_name,DIGEST_SIZE);
	
	ret=TCM_LibInit_tcp(tcm_libinfo);
    }
    return 0;
}

int tcm_libinit_start(void * sub_proc, void * para)
{
	int ret;
	void * recv_msg;
	int type;
	int subtype;
	// add yorself's module exec func here

	while(1)
	{
		usleep(time_val.tv_usec);
		ret=ex_module_recvmsg(sub_proc,&recv_msg);
		if(ret<0)
			continue;
		if(recv_msg==NULL)
			continue;
		type=message_get_type(recv_msg);
		subtype=message_get_subtype(recv_msg);
		if(!memdb_find_recordtype(type,subtype))
		{
			printf("message format (%d %d) is not registered!\n",
			message_get_type(recv_msg),message_get_subtype(recv_msg));
			continue;
		}
		ret=proc_attach_libinfo(sub_proc,recv_msg);
	}

	return 0;
}

int proc_attach_libinfo(void * sub_proc,void * recv_msg)
{
	int ret=0;
	int fd;

	RECORD(TCM_LIBINFO,LIBINFO)  * tcm_libinfo;
	void * new_msg;

	printf("begin tcm libinfo attach!\n");
    DB_RECORD * db_record;

    db_record = memdb_find_byname("default",TYPE_PAIR(TCM_LIBINFO,LIBINFO));
    if(db_record != NULL)
    {
         ret=message_add_expand_data(recv_msg,TYPE_PAIR(TCM_LIBINFO,LIBINFO),db_record->record);   
    }

	ret=ex_module_sendmsg(sub_proc,recv_msg);

	return ret;
}
